Macで任意のアプリケーションをSOCKSプロキシ経由にしてみたかったので試してみた
Macでは「ネットワーク環境設定 > Wi-Fi > 詳細 >プロキシ」でSOCKSプロキシ設定が可能です。一方で、この設定だと基本的にMacのネットワーク設定を参照するアプリケーションには全てプロキシが適用されます。(ターミナル上でのsshやcurlなどのCLIアプリケーションやGoogle Chromeなど、適用されないものもある)
そこで今回は「任意のアプリケーションのみに適用することはできるか?」ということが気になったので色々と試してみました。
前提条件
OSはMacを利用しており、バージョンは 10.15.4
です。
また、プロキシ経由での接続検証としては、DB接続クライアントであるDBeaver
を利用し、プロキシ経由でしか繋がらないDBへ接続テストをすることで検証としました。
試したもの
今回は以下を試してみました。
- Proxifier(有償)
- Proximac(オープンソース)
- tsocks(オープンソース)
最初に結論!
最初に結論を書くと、試した限りでは「Proxifier」のみが期待通りの動作をしてくれました。
1. Proxifier
ProxifierはMac、Windows共にサポートしているプロキシクライアントです。HTTPS、SOCKS(v4, v5)に対応しており、Ruleを設定することで任意のアプリケーションを任意のプロキシ経由で接続させることができます。
ダウンロードとインストール
公式サイトから、ダウンロードしてインストールします。今回は「31-day Free Trial」でお試しをしました。
使い方
基本的な使い方としては、以下のようになります。
Proxiesの設定
まずは、プロキシサーバの設定を行います。Proxies
ボタンをクリックしてプロファイルダイアログを表示させます。
Add...
ボタンをクリックしてプロキシ設定ダイアログを表示させます。
Address
とPort
に接続するプロキシサーバのアドレスとポートを、Protocol
にプロキシサーバのプロトコルの指定をしてOK
をクリックします。
「このプロキシをProxifierがデフォルトで利用するようにしますか?」と聞かれるのでNo
にします。
これでプロキシサーバの設定ができました。
Rulesの設定
次に、プロキシを適用するルールを設定します。Rules
ボタンをクリックしてプロファイルダイアログを表示させると、デフォルトでは すべて直接接続になっていることが分かります。
Add...
ボタンをクリックしてルール設定ダイアログを表示させます。
Name
に適宜名前を入力します。「前提条件」で書いた通り、今回はDBeaver
で試したいのでDBeaver
としました。名前を入れたら、Applications
の箇所の+
ボタンをクリックしてアプリケーションを指定します。
アプリケーションの選択ダイアログが表示されるのでDBeaver
を指定してOpen
をクリックします。
すると、アプリケーションがネットワーク接続で利用するモジュールも自動で検出して、追加するか聞いてくれるのでYes
をクリックします。
最後にAction
に先程設定したプロキシサーバを指定してOK
をクリックします。
これで、指定したアプリケーションだけプロキシサーバを経由する設定になりました。(プロファイルダイアログは閉じて大丈夫です)
DBeaverで検証
では、DBeaverを起動して検証してみます。プロキシサーバ経由でしか接続できないDB接続を事前に設定しているので、「接続設定 > テスト接続」から試してみます。
接続できました!
Proxifier
のログからも、ちゃんとハンドリングしてプロキシサーバ経由接続になっていることが分かります。
検証は以上です。期待通りに動いてくれていますね。
2. Proximac
Proximacはオープンソースで公開されているコマンドラインベースのProxifier代替ソフトです。対応OSは名前からも分かるようにMacOSのみとなっています。
インストールと利用方法
GitHubリポジトリのREADME.md
におけるUsage
に従ってインストールと実行を行います。
インストール、のその前に...
最初のステップが、なにやら面倒そうなので、改めてこの手順で何を行うのか確認しておきます。
「リカバリモードで csrutil enable --without kext --without debug
を実行」という旨が記載されていますが、これは何を意味しているのでしょうか?
まず、MacOSですがEl Capitan
からSystem Integrity Protection (SIP)
というシステムファイルの書き換えを保護する仕組みが導入されているとのことです。これにより、セキュリティを高めているということですね。
csrutil
コマンドはこのSIPの設定を変更するコマンドになるそうです。更に、オプションの--without kext --without debug
は何を意味しているのでしょうか?
これは、下記サイトを参照させて頂いたところ、--without kext
で「未署名のカーネル拡張モジュールを許可」するようになる、と分かりました。
セキュリティに影響を及ぼす変更となるので、設定する際にはその旨を理解した上で設定すると良いですね。
1. System Integrity Protection (SIP)の設定変更
では、設定変更を進めます。
まず最初にREADME.md
に記載のOSX 10.10+
に当てはまるかな?と思い、以下のコマンドを実行してみましたがエラーになりました。
$ sudo nvram boot-args="debug=0x146 kext-dev-mode=1" nvram: Error setting variable - 'boot-args': (iokit/common) not permitted
これがまさに上記のSIPの制約によるものなので、「復元モード」での対応が必要でした。「復元モード」の起動の仕方は下記の公式ドキュメントに記載の通りです。
OS起動後に、ロゴが出るまでCommand + R
を押して「復元モード」で起動します。起動すると言語選択画面が表示されるので「日本語」を選択して、次に進みます。
「パスワードが分かっているユーザーを選択」と出たら、選択して次に進むと「macOSユーティリティ」が起動します。
ここまで来たら画面上部のメニューバーが表示されているので「ユーティリティ > ターミナル」からターミナルを起動し、コマンドを実行してSIPの設定を変更します。
# csrutil enable --without kext --without debug csrutil: requesting an supported configuration. This is likely to break in the future and leave your machine in an unknown state. csrutil: requesting an supported configuration. This is likely to break in the future and leave your machine in an unknown state. Successfully enabled System Integrity Protection. Please restart machine for the changes to take effect.
設定変更が成功し再起動するように促されるので、メニューバーの「Appleロゴ > 再起動」から再起動をします。
再起動が終わったら、ターミナルからSIPの状態を確認します。
$ csrutil status System Integrity Protection status: unknown (Custom Configuration). Configuration: Apple Internal: disabled Kext Signing: disabled Filesystem Protections: enabled Debugging Restrictions: disabled DTrace Restrictions: enabled NVRAM Protections: enabled BaseSystem Verification: enabled This is an unsupported configuration, likely to break in the future and leave your machine in an unknown state.
Kext Signing
とDebugging Restrictions
がdisabled
になっており、想定通り設定変更されていそうですね。
2. libuvのインストール
これは単純にbrewでインストールすればOKですね。
$ brew install libuv (略) ==> Downloading https://homebrew.bintray.com/bottles/libuv-1.37.0.catalina.bottle.tar.gz ==> Downloading from https://akamai.bintray.com/d4/d4e33db48819f466b6b1391242f95f1e61ccd0e27418693610a5eeec20633350?__gd ######################################################################## 100.0% ==> Pouring libuv-1.37.0.catalina.bottle.tar.gz ? /usr/local/Cellar/libuv/1.37.0: 48 files, 3MB
3. proximacのインストール
ここで、ようやく本体をインストールします。
$ curl -fsSL https://raw.githubusercontent.com/proximac-org/proximac-install/master/install.py |sudo python Password: Resources has been downloaded! Now change kernel extension's owner Please enter your password to obtain root priviledge Proximac is successfully installed! To uninstall, just delete these files: /usr/local/proximac/* (root) /usr/local/bin/proximac
これで完了です。
4. configファイルの設定
README.md
のサンプルにあるようにconfigファイルを作成します。
process_name
に、プロキシサーバ経由にしたいアプリケーションを、local_address
とlocal_port
に利用したいSOCKSプロキシサーバのアドレスとポートを指定してみます。proximac_port
は不明ですが、そのままにしておくようにREADMEに記載があるのでそのままとします。
Leave proximac_port alone because this is now hardcoded in kext source.
{ "process_name": ["dbeaver"], "local_port":1080, "local_address":"proxy.sample.com", "proximac_port":8558, }
5. proximacの実行
configファイルを作成したら、下記のコマンドで実行してみます。
$ proximac start -c ~/.proximac.conf Password: 2020-05-21 13:45:21 INFO: Process List: 2020-05-21 13:45:21 INFO: 1. dbeaver hash -38524903 2020-05-21 13:45:21 INFO: Hook Succeed! 2020-05-21 13:45:21 INFO: The total number of process that will be hooked = 1 2020-05-21 13:45:21 INFO: Listening on 8558
実行できているように見えます。
DBeaverで検証
では、DBeaverを起動して検証してみます。先程と同様に「接続設定 > テスト接続」から試してみます。
接続できません…。タイムアウトしました。
config設定に問題があるのかなと思い、プロセス名にProxifierが自動検出してくれたプロセス名を入れたり、プロキシサーバへの接続をローカルにして、プロキシサーバとローカルをsocatで繋げてみたりしましたが、改善しませんでした。
$ socat tcp4-listen:1080,reuseaddr,fork TCP:proxy.sample.com:1080
{ "process_name": ["dbeaver","java","jcmd","jinfo","jmap","jps","jrunscript","jspawnhelper","jstack","jstat","keytool","pack200","rmid","rmiregistry","unpack200"], "local_port":1080, "local_address":"127.0.0.1", "proximac_port":8558, }
また、別途以下のconf設定にしてcurl
を対象として検証をしてみました。
{ "process_name": ["curl"], "local_port":1080, "local_address":"127.0.0.1", "proximac_port":8558, }
$ curl inet-ip.info xxx.xxx.xxx.xxx ← proxy経由で想定されるGlobal IP
これは、問題なく想定通りの動きですね。以上の試行錯誤により、以下の結果が分かりました。
process_name
でアプリケーションを指定しても想定通りに動かないアプリもあるlocal_address
にはリモートのプロキシサーバ指定はできない- curlは動いた
- CLIアプリケーションだけうまくいく可能性がある
目的としてはMacのGUIアプリケーションを動かしたかったのですが、今回の検証ではうまくいきませんでした。もし情報をお持ちの方がいたら教えて頂けると喜びます!
3. tsocks
tsocksもオープンソースで公開されているコマンドラインベースで透過的にプロキシ経由でネットワーク接続を行うソフトです。
インストールと利用方法
公式には上記のようにSourceForgeで公開されていますが、有志でGitHubにもいくつかリポジトリが公開されているようです。 私は以下のリポジトリを参考にインストールを行いました。brewによるインストールもいくつか見つけましたが、うまく動かないようなので最終的にはソースコードからmakeをすることにしました。
1. tsocksのインストール
GitHubリポジトリのtsocks/INSTALL.osxに従ってインストールを行います。まずは記載されている手順通り以下を実行します。
$ autoconf $ ./configure --prefix=/usr $ make $ sudo make install /bin/sh mkinstalldirs "/usr/bin" /usr/bin/install -c tsocks /usr/bin install: /usr/bin/tsocks: Operation not permitted make: *** [installscript] Error 71
すると、インストール途中でエラーになりました。このエラーはSIPによる書き込みエラーです。下記の記事を参考にさせて頂き、Proximacでの実施と同様にリカバリモードでOSを起動し直して、一旦オフにしました。
# csrutil disable Successfully disabled System Integrity Protection. Please restart machine for the changes to take effect.
再起動したら、SIPがオフになっているか確認します。
$ csrutil status System Integrity Protection status: disabled.
オフになっていますね。更に、書き込みをさせるには下記のようにマウントし直す必要があるとのことなのでマウントし直します。
$ sudo mount -uw /
では、再度インストールします。
$ sudo make install Password: /bin/sh mkinstalldirs "/usr/bin" /usr/bin/install -c tsocks /usr/bin /bin/sh mkinstalldirs "/usr/lib" /usr/bin/install -c libtsocks.dylib.1.8 /usr/lib ln -sf libtsocks.dylib.1.8 /usr/lib/libtsocks.dylib.1 ln -sf libtsocks.dylib.1 /usr/lib/libtsocks.dylib /bin/sh mkinstalldirs "/usr/share/man/man1" /usr/bin/install -c -m 644 tsocks.1 /usr/share/man/man1/ /bin/sh mkinstalldirs "/usr/share/man/man8" /usr/bin/install -c -m 644 tsocks.8 /usr/share/man/man8/ /bin/sh mkinstalldirs "/usr/share/man/man5" /usr/bin/install -c -m 644 tsocks.conf.5 /usr/share/man/man5/
無事、インストールできました!あとは/usr/bin/tsocks
に記載されているLIBDIR
を/usr/lib
に変更して完了です。
$ sudo vim /usr/bin/tsocks
(~略~) LIBDIR=/usr/lib (~略~)
2. confファイルの設定
confファイルは以下のように作成します。ファイルパスは/etc/tsocks.conf
です。
server = 127.0.0.1 server_type = 5 server_port = 1080
3. tsocksの実行
confファイルを作成したら実行してみます。使い方はシェルで実行ファイルの前にtsocks
を指定するだけです。
まずはsocat
を利用して、ローカルの1080
への通信をリモートのプロキシサーバへ転送するようにします。
$ socat tcp4-listen:1080,reuseaddr,fork TCP:proxy.sample.com:1080
これで127.0.0.1:1080
がproxy.sample.com:1080
に飛ぶようになったので、下記のコマンドで試してみます。
$ tsocks /Applications/DBeaver.app/Contents/MacOS/dbeaver
が、こちらもproximacと同様にダメでした。また、試しにcurlで試したところ、こちらはproximacと同様に成功しました。
$ tsocks curl inet-ip.info xxx.xxx.xxx.xxx ← proxy経由で想定されるGlobal IP
まとめ
以上、Macで任意のアプリケーションをSOCKSプロキシ経由にしてみようと試してみた結果でした!
今回、できればProximacやtsocksでうまく任意のアプリケーションをSOCKSプロキシ経由で動かしたかったのですが、試した限りではProxifierが断然良い感じに動くことが分かりました。
どなたかのお役に立てば幸いです。それでは!